package com.rabbit.eap.system.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.rabbit.eap.config.properties.EapProperties;
import com.rabbit.eap.framework.common.api.ApiResult;
import com.rabbit.eap.framework.common.enums.MsgEnum;
import com.rabbit.eap.framework.common.exception.EapException;
import com.rabbit.eap.framework.common.service.impl.BaseServiceImpl;
import com.rabbit.eap.framework.core.pagination.PageInfo;
import com.rabbit.eap.framework.core.pagination.Paging;
import com.rabbit.eap.framework.shiro.util.SaltUtil;
import com.rabbit.eap.framework.shiro.vo.LoginSysUserVO;
import com.rabbit.eap.framework.utils.JsonUtils;
import com.rabbit.eap.framework.utils.LoginUtil;
import com.rabbit.eap.framework.utils.PasswordUtil;
import com.rabbit.eap.system.component.SysPermissionService;
import com.rabbit.eap.system.constant.SystemConstant;
import com.rabbit.eap.system.dto.IdDTO;
import com.rabbit.eap.system.dto.ModifyPwdDTO;
import com.rabbit.eap.system.dto.SysUserDTO;
import com.rabbit.eap.system.entity.*;
import com.rabbit.eap.system.enums.UserStateEnum;
import com.rabbit.eap.system.mapper.SysUserMapper;
import com.rabbit.eap.system.param.SysUserPageParam;
import com.rabbit.eap.system.service.*;
import com.rabbit.eap.system.vo.SysUserVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * @projectName: eap
 * @packageName: com.rabbit.eap.system.service.impl
 * @className SysUserServiceImpl
 * @author： rabbit
 * @version： 1.0
 * @since： 2020/06/06 23:34:03
 * <p>Description:
 * 用户信息表 服务实现类
 * </p>

 */
@Slf4j
@Service
public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser> implements ISysUserService {

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private EapProperties eapProperties;

    @Autowired
    private ISysUserDeptService iSysUserDeptService;

    @Autowired
    private ISysUserPostService iSysUserPostService;

    @Autowired
    private ISysUserRoleService iSysUserRoleService;

    @Autowired
    private ISysConfigService iSysConfigService;

    @Autowired
    private SysPermissionService sysPermissionService;


    /**
     * @param sysUserDTO:sysUserDTO数据传输对象
     * @throws Exception
     * @Description: 添加用户信息表
     * @methodName: saveSysUser
     * @return: ApiResult
     * @date: 2020/06/06 23:34:03
     * @author: rabbit
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApiResult saveSysUser(SysUserDTO sysUserDTO) throws Exception {
        SysUser selectSysUser = new SysUser().setUserName(sysUserDTO.getUserName());
        int count = sysUserMapper.selectCount(new QueryWrapper<>(selectSysUser));
        if (count > 0) {
            return ApiResult.fail(sysUserDTO.getUserName() + MsgEnum.IS_EXIST.getDesc());
        }
        if (checkPhoneUnique(sysUserDTO)) {
            return ApiResult.fail(sysUserDTO.getMobile() + UserStateEnum.MOBILE_HAS_EXIST.getDesc());
        }
        if (checkEmailUnique(sysUserDTO)) {
            return ApiResult.fail(sysUserDTO.getEmail() + UserStateEnum.EMAIL_HAS_EXIST.getDesc());
        }
        if (checkUserNumberUnique(sysUserDTO)) {
            return ApiResult.fail(sysUserDTO.getEmail(), UserStateEnum.USER_NUMBER_HAS_EXIST.getDesc());
        }
        // 生成盐值
        String salt = null;
        String password = sysUserDTO.getPassword();
        // 如果密码为空，则设置默认密码
        if (StringUtils.isBlank(password)) {
            salt = eapProperties.getLoginInitSalt();
            //系统配置取默认密码
            SysConfig sysConfig = new SysConfig().setConfigKey(SystemConstant.DEFAULT_PWD);
            if (ObjectUtil.isNotNull(sysConfig)) {
                password = sysConfig.getConfigValue();
            }
            password = eapProperties.getLoginInitPassword();
        } else {
            salt = SaltUtil.generateSalt();
        }
        // 密码加密
        sysUserDTO.setSalt(salt);
        sysUserDTO.setPassword(PasswordUtil.encrypt(password, salt));
        SysUser sysUser = sysUserDTO.convert(SysUser.class);
        boolean bool = super.save(sysUser);
        if (bool) {
            //保存附属部门
            saveSysUserDepts(sysUser);
            //保存用户岗位
            saveUserPost(sysUser);
            //保存用户角色
            saveUserRole(sysUser);
            return ApiResult.ok(MsgEnum.ADD_SUCCESS.getDesc());
        } else {
            return ApiResult.fail(MsgEnum.ADD_FAIL.getDesc());
        }
    }

    /**
     * @param sysUserDTO:sysUserDTO数据传输对象
     * @throws Exception
     * @Description 修改用户信息表
     * @methodName: modifySysUser
     * @return: ApiResult
     * @date: 2020/06/06 23:34:03
     * @author: rabbit
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApiResult modifySysUser(SysUserDTO sysUserDTO) throws Exception {
        if (checkPhoneUnique(sysUserDTO)) {
            return ApiResult.fail(sysUserDTO.getMobile(), UserStateEnum.MOBILE_HAS_EXIST.getDesc());
        }
        if (checkEmailUnique(sysUserDTO)) {
            return ApiResult.fail(sysUserDTO.getEmail(), UserStateEnum.EMAIL_HAS_EXIST.getDesc());
        }
        if (checkUserNumberUnique(sysUserDTO)) {
            return ApiResult.fail(sysUserDTO.getEmail(), UserStateEnum.USER_NUMBER_HAS_EXIST.getDesc());
        }
        SysUser sysUser = sysUserDTO.convert(SysUser.class);
        boolean bool = super.updateById(sysUser);
        if (bool) {
            iSysUserDeptService.remove(new LambdaQueryWrapper<SysUserDept>().eq(SysUserDept::getUserId, sysUser.getId()));
            //保存附属部门
            saveSysUserDepts(sysUser);
            //保存岗位
            iSysUserPostService.remove(new LambdaQueryWrapper<SysUserPost>().eq(SysUserPost::getUserId, sysUser.getId()));
            saveUserPost(sysUser);
            //保存用户角色
            iSysUserRoleService.remove(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, sysUser.getId()));
            saveUserRole(sysUser);
            return ApiResult.ok(MsgEnum.UPDATE_SUCCESS.getDesc());
        } else {
            return ApiResult.fail(MsgEnum.UPDATE_FAIL.getDesc());
        }
    }

    /**
     * @param ids:ids集合
     * @throws Exception
     * @Description 删除用户信息表
     * @methodName: removeSysUser
     * @return: ApiResult
     * @date: 2020/06/06 23:34:03
     * @author: rabbit
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApiResult removeSysUser(Long[] ids) throws Exception {
        SysConfig sysConfig = iSysConfigService.getSysConfigByKey(SystemConstant.DEFAULT_ADMIN_KEY);
        SysUser sysUser = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserName, sysConfig.getConfigValue()));

        for (Long userId : ids) {
            if (userId.equals(sysUser.getId())) {
                throw new EapException(UserStateEnum.DEFAULT_ADMIN.getDesc());
            }
        }
        boolean bool = super.removeByIds(Arrays.asList(ids));
        if (bool) {
            return ApiResult.ok(MsgEnum.DELETE_SUCCESS.getDesc());
        } else {
            return ApiResult.fail(MsgEnum.DELETE_FAIL.getDesc());
        }
    }

    /**
     * @param id: id
     * @throws Exception
     * @Description 根据Id获取用户信息表详情
     * @methodName: getSysUserInfo
     * @return: ApiResult
     * @date: 2020/06/06 23:34:03
     * @author: rabbit
     */
    @Override
    public ApiResult getSysUserById(Long id) throws Exception {
        if (ObjectUtil.isNull(id)) {
            return ApiResult.fail(MsgEnum.PARAM_NOT_NULL.getDesc());
        }
        //List<SysUserDeptVO> list = BeanConverter.convert(SysUserDeptVO.class, sysUserMapper.getSysUserDept(id));
        SysUserVO sysUserVO = sysUserMapper.getSysUserById(id);
        //sysUserVO.setSysUserDepts(list);
        return ApiResult.ok(sysUserVO);
    }

    /**
     * @param sysUserPageParam
     * @throws Exception
     * @Description 用户信息表分页列表
     * @methodName: getSysUserPageList
     * @return: ApiResult
     * @date: 2020/06/06 23:34:03
     * @author: rabbit
     */
    @Override
    public ApiResult getSysUserPageList(SysUserPageParam sysUserPageParam) throws Exception {
        Page<SysUser> page = new PageInfo<>(sysUserPageParam);
        IPage<SysUserVO> iPage = sysUserMapper.getSysUserPageList(page, sysUserPageParam);
        Paging<SysUserVO> paging = new Paging<SysUserVO>(iPage);
        return ApiResult.ok(paging);
    }

    /**
     * @param sysUser:
     * @Description: 保存附属机构
     * @methodName: saveSubsidiaries
     * @return: void
     * @date: 2020/7/12 20:27
     * @author: rabbit
     */
    private void saveSysUserDepts(SysUser sysUser) {
        Long userId = sysUser.getId();
        List<SysUserDept> list = sysUser.getSysUserDepts();
        if (ObjectUtil.isNotNull(list)) {
            list.forEach(sysUserDept -> {
                sysUserDept.setUserId(userId);
            });
            if (CollectionUtils.isNotEmpty(list)) {
                iSysUserDeptService.saveBatch(list);
            }
        }
    }

    /**
     * @param sysUser:
     * @Description: 保存用户岗位
     * @methodName: saveUserPost
     * @return: void
     * @date: 2020/7/12 20:35
     * @author: rabbit
     */
    private void saveUserPost(SysUser sysUser) {
        Long userId = sysUser.getId();
        Long[] posts = sysUser.getPostIds();
        if(ObjectUtil.isNotNull(posts)) {
            List<SysUserPost> list = Lists.newArrayList();
            for (Long postId : posts) {
                SysUserPost sysUserPost = new SysUserPost().setUserId(userId).setPostId(postId);
                list.add(sysUserPost);
            }
            if (CollectionUtils.isNotEmpty(list)) {
                iSysUserPostService.saveBatch(list);
            }
        }
    }

    /**
     * @param sysUser:
     * @Description: 保存用户角色
     * @methodName: saveUserRole
     * @return: void
     * @date: 2020/7/12 20:42
     * @author: rabbit
     */
    private void saveUserRole(SysUser sysUser) {
        Long userId = sysUser.getId();
        Long[] roles = sysUser.getRoleIds();
        List<SysUserRole> list = Lists.newArrayList();
        for (Long roleId : roles) {
            SysUserRole sysUserRole = new SysUserRole().setUserId(userId).setRoleId(roleId);
            list.add(sysUserRole);
        }
        if (CollectionUtils.isNotEmpty(list)) {
            iSysUserRoleService.saveBatch(list);
        }
    }

    /**
     * @param user:
     * @Description: 校验手机号是否唯一
     * @methodName: checkPhoneUnique
     * @return: boolean
     * @date: 2020/7/12 20:55
     * @author: rabbit
     */
    private boolean checkPhoneUnique(SysUserDTO user) {
        Long userId = ObjectUtil.isNull(user.getId()) ? -1L : user.getId();
        SysUser info = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getMobile, user.getMobile()));
        if (ObjectUtil.isNotNull(info) && info.getId().longValue() != userId.longValue()) {
            return true;
        }
        return false;
    }

    /**
     * @param user:
     * @Description: 校验邮箱是否唯一
     * @methodName: checkEmailUnique
     * @return: boolean
     * @date: 2020/7/12 20:55
     * @author: rabbit
     */
    private boolean checkEmailUnique(SysUserDTO user) {
        Long userId = ObjectUtil.isNull(user.getId()) ? -1L : user.getId();
        SysUser info = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getEmail, user.getEmail()));
        if (ObjectUtil.isNotNull(info) && info.getId().longValue() != userId.longValue()) {
            return true;
        }
        return false;
    }
    /**
     * @param user:
     * @Description: 校验工号是否唯一
     * @methodName: checkEmailUnique
     * @return: boolean
     * @date: 2020/7/12 20:55
     * @author: rabbit
     */
    private boolean checkUserNumberUnique(SysUserDTO user) {
        Long userId = ObjectUtil.isNull(user.getId()) ? -1L : user.getId();
        SysUser info = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserNumber, user.getUserNumber()));
        if (ObjectUtil.isNotNull(info) && info.getId().longValue() != userId.longValue()) {
            return true;
        }
        return false;
    }

    /**
     * @param idDTO:
     * @Description: 重置密码
     * @methodName: resetPwd
     * @return: com.rabbit.eap.framework.common.api.ApiResult
     * @date: 2020/7/12 21:27
     * @author: rabbit
     */
    @Override
    public ApiResult resetPwd(IdDTO idDTO) {
        if (ObjectUtil.isEmpty(idDTO.getId())) {
            return ApiResult.fail(UserStateEnum.USER_ID.getDesc() + MsgEnum.NOT_NULL.getDesc());
        }
        SysUser sysUser = sysUserMapper.selectById(idDTO.getId());
        //系统配置取默认密码
        SysConfig sysConfig = new SysConfig().setConfigKey(SystemConstant.DEFAULT_PWD);
        SysConfig config = iSysConfigService.getOne(new LambdaQueryWrapper<>(sysConfig));
        String configValue = config.getConfigValue();
        Map<String, Object> map = JsonUtils.toMap(configValue);
        String password = map.get(SystemConstant.INITPWD).toString();
        String salt = map.get(SystemConstant.INITSALT).toString();
        sysUser.setSalt(salt);
        sysUser.setPassword(PasswordUtil.encrypt(password, salt));
        boolean bool = super.updateById(sysUser);
        if (bool) {
            return ApiResult.ok(UserStateEnum.reset_pwd_success.getDesc());
        } else {
            return ApiResult.fail(UserStateEnum.reset_pwd_fail.getDesc());
        }
    }

    /**
     * @param modifyPwdDTO :
     * @Description: 修改密码
     * @methodName: modifyPwd
     * @return: com.rabbit.eap.framework.common.api.ApiResult
     * @date: 2020/7/12 21:27
     * @author: rabbit
     */
    @Override
    public ApiResult modifyPwd(ModifyPwdDTO modifyPwdDTO) {
        boolean bool = changePwd(modifyPwdDTO);
        if (bool) {
            return ApiResult.ok(UserStateEnum.modify_pwd_success.getDesc());
        } else {
            return ApiResult.fail(UserStateEnum.modify_pwd_fail.getDesc());
        }
    }

    /**
     * @param sysUserDTO:
     * @Description: 修改用户状态
     * @methodName: changeUserStatus
     * @return: com.rabbit.eap.framework.common.api.ApiResult
     * @date: 2020/7/12 21:28
     * @author: rabbit
     */
    @Override
    public ApiResult changeUserStatus(SysUserDTO sysUserDTO) {
        SysUser sysUser = new SysUser().setId(sysUserDTO.getId()).setStatus(sysUserDTO.getStatus());
        int bool = sysUserMapper.updateById(sysUser);
        if (bool > 0) {
            return ApiResult.ok(UserStateEnum.change_status_success.getDesc());
        } else {
            return ApiResult.fail(UserStateEnum.change_status_fail.getDesc());
        }
    }

    /**
     * @param modifyPwdDTO:
     * @Description: 重置或者修改密码
     * @methodName: changePwd
     * @return: boolean
     * @date: 2020/7/12 21:46
     * @author: rabbit
     */
    private boolean changePwd(ModifyPwdDTO modifyPwdDTO) {
        Long userId = modifyPwdDTO.getId();
        SysUser sysUser = sysUserMapper.selectById(userId);
        String salt = sysUser.getSalt();
        String password = modifyPwdDTO.getNewPassword();
        sysUser.setSalt(salt);
        sysUser.setPassword(PasswordUtil.encrypt(password, salt));
        return super.updateById(sysUser);
    }

    @Override
    public ApiResult<LoginSysUserVO> getInfo() {
        Long userId = LoginUtil.getUserId();
        SysUser sysUser = sysUserMapper.selectById(userId);
        LoginSysUserVO loginSysUser = sysPermissionService.getLoginSysUser(sysUser);
        return ApiResult.ok(loginSysUser);
    }

    @Override
    public ApiResult<List<SysMenu>> getUserMenu() {
        Long userId = LoginUtil.getUserId();
        SysUser sysUser = sysUserMapper.selectById(userId);
        List<SysMenu> list = sysPermissionService.getUserMenu(sysUser);
        return ApiResult.ok(list);
    }
}
